package william.list;

/**
 * @author ZhangShenao
 * @date 2024/3/12
 * @description
 */
public class Leetcode25_K个一组反转链表 {
    private class ListNode {
        int val;
        ListNode next;

        ListNode() {
        }

        ListNode(int val) {
            this.val = val;
        }

        ListNode(int val, ListNode next) {
            this.val = val;
            this.next = next;
        }
    }

    /**
     * 遍历链表,每次找到一组k个节点,进行反转操作
     * 如果当前组中节点不足k个,则直接终止
     * <p>
     * 时间复杂度 O(N*N) 遍历O(N)x反转O(N)
     * 空间复杂度 O(1)
     */
    public ListNode reverseKGroup(ListNode head, int k) {
        //边界条件校验
        if (head == null || k <= 1) {
            return head;
        }

        //借助哑头节点
        ListNode dummy = new ListNode();
        dummy.next = head;
        ListNode pre = dummy;

        //遍历链表,每次找到一组k个节点,进行反转操作
        while (pre.next != null) {
            ListNode start = pre.next;
            ListNode end = pre;
            for (int i = 0; i < k && end != null; i++) {
                end = end.next;
            }
            if (end == null) {   //当前组中节点数量不足k个,直接终止
                break;
            }

            //记录下一个节点
            ListNode next = end.next;

            //切断当前组节点与其余节点的联系
            end.next = null;

            //将[start,end]之间的节点进行反转
            pre.next = reverse(start);

            //将反转后的链表接回原链表
            start.next = next;

            //继续反转下一组
            pre = start;
        }

        //返回头结点
        return dummy.next;
    }

    /**
     * 反转以head为头的链表,并返回反转后的头节点
     */
    private ListNode reverse(ListNode head) {
        ListNode pre = null;
        ListNode cur = head;
        ListNode next = null;

        while (cur != null) {
            next = cur.next;
            cur.next = pre;

            pre = cur;
            cur = next;
        }

        return pre;
    }
}
